package Datenbank;

import java.rmi.RemoteException;
import java.sql.*;
import java.util.Vector;
import Applikationslogik.*;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Bildet Objekte des Typs Kategorie auf der relationalen Datenbank ab.
 * Die Klasse beinhaltet Methoden und Objekte zum Anlegen, Ändern, Löschen und Suchen.
 *
 * @author Daniel Mossiossian & René van Straaten
 */
public class KategorieMapper {

    private static KategorieMapper kategorieMapper = null;

    /**
     * Stellt sicher, dass nur eine Instanz von KategorieMapper erzeugt wird.
     *
     * @return kategorieMapper das KategorieMapper-Objekt
     */
    public static KategorieMapper KategorieMapper() {
        if (kategorieMapper == null) {
            kategorieMapper = new KategorieMapper();
        }
        return kategorieMapper;
    }

    /**
     * Fügt ein neues Kategorie- Objekt in die Datenbank ein.
     * Dabei wird auch überprüft, welche die bisher höhste kategorie_id (der Primärschlüssel) ist.
     *
     * @param kt das zu speichernde Kategorie-Objekt
     * @return kt das bereits übergebene Objekt, jedoch mit ggf. korrigierter
     *         kategorie_id vom Typ Kategorie
     */
    public Kategorie insert(Kategorie kt) {
        Connection con = DBConnection.connection();

        try {
            Statement stmt = con.createStatement();

            /*
             * Hier wird überprüft welche Kategorie ID bisher die höhste ist.
             */
            ResultSet rs = stmt.executeQuery(
                    "SELECT MAX(kategorie_id) AS maxid " +
                    "FROM Kategorie");


            if (rs.next()) {
                try {
                    /* Hier wird die bisher höhste vorhandene kategorie_id um +1 erhöht.
                     */
                    kt.set_kategorie_id(rs.getInt("maxid") + 1);

                    stmt = con.createStatement();

                    /* Die tatsächliche Einfügeoperation mit den übergebenden Attributen.
                     */

                    stmt.executeUpdate("INSERT INTO Kategorie (kategorie_id, titel, person_id) VALUES (" +
                            kt.get_kategorie_id() + ",'" +
                            kt.get_name() + "'," +
                            kt.get_person_id() + ")");

                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        } catch (SQLException e2) {
            e2.printStackTrace();
        }
        /* Rückgabe des angelegten Objekts kt von Typ Kategorie
         */
        return kt;
    }

    /**
     * Aktualisiert das übergebene Kategorie- Objekt in der Datenbank.
     *
     * @param kt das zu aktualisierende Kategorie- Objekt
     * @return kt das als Parameter übergebende Objekt vom Typ Kategorie
     */
    public Kategorie update(Kategorie kt) {
        /* Stellt durch Aufruf der connection() Methode der DBConnection-Klasse, die Verbindung zur Datenbank her. */
        Connection con = DBConnection.connection();

        try {
            // Leeres SQL-Statement stmt wird angelegt.
            Statement stmt = con.createStatement();

            //Statement wird ausgefüllt und als Query an die DB geschickt.
            stmt.executeUpdate("UPDATE Kategorie " +
                    "SET kategorie_id=" + kt.get_kategorie_id() + "," +
                    "titel='" + kt.get_name() + "', " +
                    "person_id=" + kt.get_person_id() + " " +
                    "WHERE kategorie_id=" + kt.get_kategorie_id());

        } catch (SQLException e2) {
            e2.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        // Das als Parameter übergebende Objekt vom Typ Kategorie wird zurückgegeben
        return kt;
    }

    /**
     * Löscht alle Daten eines Kategorie- Objekts aus der Datenbank.
     *
     * @param kt das zu löschende Kategorie- Objekt
     */
    public void delete(Kategorie kt) {
        Connection con = DBConnection.connection();

        try {
            // Leeres SQL-Statement stmt wird angelegt.
            Statement stmt = con.createStatement();

            // Statement wird ausgefüllt und als Query an die DB geschickt.
            stmt.executeUpdate("DELETE FROM Kategorie " +
                    "WHERE kategorie_id=" + kt.get_kategorie_id());

        } catch (SQLException e2) {
            e2.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }


    }

    /**
     * Findet alle Kategorien anhand der ID einer Person.
     *
     * @return result Ergebnisvektor mit Kategorien-Objekten, d.h. allen in der Datenbank angelegten Kategorien. Bei evtl. Exceptions
     *         wird ein partiell gefüllter oder ggf. auch leerer Vektor vom Typ Kategorie zurückgeliefert.
     */
    public Vector findallKategorie_byPerson(int person_id) {
        Connection con = DBConnection.connection();
        Vector result = new Vector();

        try {
            Statement stmt = con.createStatement();


            ResultSet rs = stmt.executeQuery(

                    "SELECT * " +
                    "FROM Kategorie");
                    //"WHERE person_id=" + person_id);

            // Für jeden Eintrag im Suchergebnis wird nun ein Kategorie-Objekt kt erstellt.
            while (rs.next()) {
                try {
                    KategorieImpl kt = new KategorieImpl();
                    kt.set_kategorie_id(rs.getInt("kategorie_id"));
                    kt.set_name(rs.getString("titel"));
                    kt.set_person_id(rs.getInt("person_id"));
                    result.addElement(kt);
                    // Wenn kein Titel vorhanden ist bleibt der String Titel des Vectors leer
                } catch (Exception e) {
                    e.printStackTrace();
                    //Bei einer evtl. Exception wird die while-Schleife abgebrochen.
                    break;
                }

            }
        } catch (SQLException e2) {
            e2.printStackTrace();
        }
        // Ergebnisvektor vom Typ Kategorie wird zurückgeben.
        return result;

    }

    /**
     * Findet alle Kategorien.
     *
     * @return result Ergebnisvektor mit Kategorie-Objekten, d.h. allen in der Datenbank angelegte Kategorien, zurückgegeben.
     * Bei evtl. Exceptions wird ein partiell gefüllter oder ggf.
     * auch leerer Vektor vom Typ Kategorie zurückgeliefert.
     */
    public Vector findallKategorie() {
        Connection con = DBConnection.connection();
        Vector result = new Vector();

        try {
            Statement stmt = con.createStatement();
            ResultSet rs = stmt.executeQuery(

                    "SELECT * " +
                    "FROM Kategorie ");

            // Für jeden Eintrag im Suchergebnis wird nun ein Kategorie- Objekt kt erstellt.
            while (rs.next()) {
                try {
                    KategorieImpl kt = new KategorieImpl();
                    kt.set_kategorie_id(rs.getInt("kategorie_id"));
                    kt.set_name(rs.getString("titel"));
                    kt.set_person_id(rs.getInt("person_id"));
                    result.addElement(kt);
                } catch (Exception e) {
                    e.printStackTrace();
                    //Bei einer evtl. Exception wird die while-Schleife abgebrochen.
                    break;
                }
           }
        } catch (SQLException e2) {
            e2.printStackTrace();
        }
        // Ergebnisvektor vom Typ Kategorie wird zurückgeben.
        return result;
    }

    /**
     * Überprüft welche Kategorie von welcher Person stammt.
     *
     * @param x das Person- Objekt
     * @return true, falls es eine Kategorie gibt, andernfalls false
     */
    public boolean check_kategorie_exists_byperson (Person x)
    {
        int anzahl = 5;
        Connection con = DBConnection.connection();
        try {
            Statement stmt = con.createStatement();
            ResultSet rs = stmt.executeQuery(
                   "SELECT COUNT(*) AS count " +
                    "FROM Kategorie " +
                    "WHERE person_id=" + x.get_person_id());

            while (rs.next()) {
            anzahl = rs.getInt("count");
            }

        } catch (RemoteException ex) {
            Logger.getLogger(KategorieMapper.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SQLException e2) {
            e2.printStackTrace();
        }
        // Wenn es keine Einträge mehr gibt- false, sonst true
        System.out.println("------------ check_kategorie_exists_byperson ----------------");
        System.out.println("Anzahl der noch verknüpften Kategorien: "+anzahl);
        if(anzahl==0)
            return false;
        else
            return true;
    }

    /**
     * Sucht in der Datenbank nach einer Kategorie mit der eingegebenen ID.
     *
     * @param id das Primärschlüsselattribut Kategorie in der Datenbank
     * @return Das Objekt vom Typ Kategorie, das der id entspricht, wird zurückgegen.
     *         Null wird zurückgegeben, wenn das Objekt nicht in der Datenbank vorhanden ist. Da es
     *         sich um einen Primärschlüssel handelt und dieser somit eindeutig ist, wird genau ein Objekt zurückgegeben.
     */
    public Kategorie findbyid(int id) {
        Connection con = DBConnection.connection();

        try {
            Statement stmt = con.createStatement();

            ResultSet rs = stmt.executeQuery(
                    "SELECT * FROM Kategorie " +
                    "WHERE kategorie_id =" + id);

            /*
             * Da es sich bei id um einen Primärschlüssel handelt, kann max. nur ein Tupel zurückgegeben werden.
             * Es wird geprüft, ob ein Ergebnis vorliegt. Wenn ja, werden die Attribute kategorie_id, titel
             * und person_id ausgelesen und als Typ Kategorie zurückgegeben.
             */
            if (rs.next()) {
                try {
                    KategorieImpl kt = new KategorieImpl();
                    kt.set_kategorie_id(rs.getInt("kategorie_id"));
                    kt.set_name(rs.getString("titel"));
                    kt.set_person_id(rs.getInt("person_id"));

                    return kt;

                } catch (Exception e) {
                    e.printStackTrace();
                    return null;
                }
            }
        } catch (SQLException e2) {
            e2.printStackTrace();
            return null;
        }
        return null;
    }
}

